package com.km.team.phsystem.service.impl;

import java.time.*;
import java.util.Date;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.km.team.phsystem.beans.pojo.BusinessStartEndInfo;
import com.km.team.phsystem.beans.pojo.QueueInfo;
import com.km.team.phsystem.beans.pojo.SystemDate;
import com.km.team.phsystem.beans.pojo.SystemDateExample;
import com.km.team.phsystem.beans.vo.DateVo;
import com.km.team.phsystem.beans.vo.TimeSlotVo;
import com.km.team.phsystem.beans.vo.WorkDateVo;
import com.km.team.phsystem.common.constants.ConstantsDateInformation;
import com.km.team.phsystem.common.enums.SystemDateEnum;
import com.km.team.phsystem.dao.mybatis.SystemDateMapper;
import com.km.team.phsystem.dao.mybatis.custom.SystemDateMapperCustom;
import com.km.team.phsystem.service.BusinessStartEndInfoService;
import com.km.team.phsystem.service.IQueueService;
import com.km.team.phsystem.service.SystemDateService;
import com.km.team.phsystem.service.TimeSlotPhConfigService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * @author ：bastr.
 * @description：
 * @date ：2018/10/20
 */
@Service("systemDateService")
public class SystemDateServiceImpl implements SystemDateService {

    private final SystemDateMapperCustom holiday;
    private final SystemDateMapper systemDateMapper;
    private final IQueueService queueService;
    private final TimeSlotPhConfigService timeSlotPhConfigService;
    private final BusinessStartEndInfoService businessStartEndInfoService;

    @Autowired
    public SystemDateServiceImpl(SystemDateMapperCustom holiday, SystemDateMapper systemDateMapper,
                                 IQueueService queueService, TimeSlotPhConfigService timeSlotPhConfigService,
                                 BusinessStartEndInfoService businessStartEndInfoService) {
        this.holiday = holiday;
        this.systemDateMapper = systemDateMapper;
        this.queueService = queueService;
        this.timeSlotPhConfigService = timeSlotPhConfigService;
        this.businessStartEndInfoService = businessStartEndInfoService;
    }

    @Override
    public List<SystemDate> selectDateForMonth(String systemDateVo) {
        return holiday.selectDateForMonth(systemDateVo);
    }

    @Override
    public int insterHoliday(List<Map<String, String>> installParams) {
        return holiday.insterHoliday(installParams);
    }

    @Override
    public List<Date> selectDateForNowAndSomeDay(Integer days) {
        List<SystemDate> systemDates = getSystemDates(days);
        List<Date> workDayList = new ArrayList<>(128);
        systemDates.forEach(item -> {
            if (item.getDateType().equals(SystemDateEnum.DATE_TYPE_WORK.getType())) {
                workDayList.add(item.getDayShortDesc());
            }
        });
        return getDates(workDayList);
    }

    private <T> List<T> getDates(List<T> workDayList) {
        LocalTime localTime = LocalTime.now().withSecond(0).withNano(0);
        LocalDate localDate = LocalDate.now();
        if(CollectionUtils.isEmpty(workDayList)){
            return null;
        }
        WorkDateVo vo = (WorkDateVo) workDayList.get(0);
        // 只有日期为当天，并且当前时间超过17点，才忽略第一个日期
        if (localTime.getHour() > 17 && vo.getDate().getDate() == localDate.getDayOfMonth()) {
            return CollUtil.sub(workDayList, 1, 32);
        }
        return CollUtil.sub(workDayList, 0, 31);
    }

    @Override
    public List<WorkDateVo> selectDateForNowAndSomeDayAndBusiness(Integer days, Integer businessId) {
        BusinessStartEndInfo businessStartEndInfo = businessStartEndInfoService.selectDataForKey(businessId);
        String startOrEnd = StringUtils.isBlank(businessStartEndInfo.getStartOrEnd()) ? SystemDateEnum.START_WORK.getType() :
            businessStartEndInfo.getStartOrEnd();
        Integer dayId = businessStartEndInfo.getDayId() == null ? 0 : Integer.valueOf(businessStartEndInfo.getDayId());
        List<SystemDate> systemDates = getSystemDates(days);
        List<WorkDateVo> workDayList = new ArrayList<>(128);
        judgeAccept(dayId, systemDates, workDayList, startOrEnd);
        return this.getDates(workDayList);
    }

    private void judgeAccept(Integer dayId, List<SystemDate> systemDates, List<WorkDateVo> workDayList,
                             String startOrEnd) {
        systemDates.forEach(item -> {
            Instant instant = item.getDayShortDesc().toInstant();
            ZoneId zone = ZoneId.systemDefault();
            LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
            int dayOfMonth = localDateTime.getDayOfMonth();
            if (SystemDateEnum.START_WORK.getType().equals(startOrEnd)) {
                if (dayOfMonth < dayId) {
                    //还未开始办理业务
                    getWorkDateVoList(workDayList, item, false);
                } else {
                    //已经开始办理业务了
                    getWorkDateVoList(workDayList, item, true);
                }
            } else {
                if (dayOfMonth > dayId) {
                    //还未开始办理业务
                    getWorkDateVoList(workDayList, item, false);
                } else {
                    //已经开始办理业务了
                    getWorkDateVoList(workDayList, item, true);
                }
            }

        });
    }

    private void getWorkDateVoList(List<WorkDateVo> workDayList, SystemDate item, Boolean falg) {
        if (item.getDateType().equals(SystemDateEnum.DATE_TYPE_WORK.getType())) {
            WorkDateVo workDateVo = new WorkDateVo();
            workDateVo.setDate(item.getDayShortDesc());
            workDateVo.setWorkDay(falg);
            workDayList.add(workDateVo);
        }
    }

    private List<SystemDate> getSystemDates(Integer days) {
        SystemDateExample systemDateExample = new SystemDateExample();
        //取时间
        Date today = new Date();
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(today);
        //把日期往后增加一天,整数  往后推,负数往前移动
        calendar.add(Calendar.DATE, days);
        //这个时间就是日期往后推一天的结果
        today = calendar.getTime();
        systemDateExample.or().andDayShortDescBetween(new Date(), today);
        return this.systemDateMapper.selectByExample(systemDateExample);
    }

    @Autowired
    private TimeSlotAssistServiceImple timeSlotAssistServiceImple;

    @Override
    public List<DateVo> selectQueueDateStatus(Integer businessId) {
        List<WorkDateVo> dateList = this.selectDateForNowAndSomeDayAndBusiness(100, businessId);
        List<QueueInfo> queueInfoList =
            this.queueService.selectDataForDateAfter(businessId, DateUtil.beginOfDay(new Date()));
        List<DateVo> resultList = new ArrayList<>(36);
        //获取该业务的所有开启时段的办理数总和
        Long acceptancesNum = Long.valueOf(this.timeSlotPhConfigService.getAcceptancesNumForBusinessId(businessId));
        Map<String, Integer> countMap = new HashMap<>(31);
        queueInfoList.forEach(item -> {
            if (countMap.containsKey(DateUtil.format(item.getDate(), ConstantsDateInformation.YYYY_MM_DD))) {
                Integer integer = countMap.get(DateUtil.format(item.getDate(), ConstantsDateInformation.YYYY_MM_DD));
                countMap.put(DateUtil.format(item.getDate(), ConstantsDateInformation.YYYY_MM_DD), ++integer);
            } else {
                countMap.put(DateUtil.format(item.getDate(), ConstantsDateInformation.YYYY_MM_DD), 1);
            }
        });
        dateList.forEach(item -> {
            DateVo dateVo = new DateVo();
            if (countMap.containsKey(DateUtil.format(item.getDate(), ConstantsDateInformation.YYYY_MM_DD))) {
                if (acceptancesNum <= countMap.get(DateUtil.format(item.getDate(),
                    ConstantsDateInformation.YYYY_MM_DD))) {
                    dateVo.setAvailable(false);
                } else {
                    dateVo.setAvailable(true);
                }
            } else {
                dateVo.setAvailable(true);
            }
            dateVo.setDate(item.getDate());
            dateVo.setWorkDateVo(item);
            resultList.add(dateVo);
        });

//        TimeSlotVo vo = timeSlotAssistServiceImple.getEnableTimeSlotListForBusinessId(businessId, date);

        return resultList;
    }


}
